#ifndef LOGIC_H
#define LOGIC_H

const int SIZE = 9;

/** \class Logic
*
*   \brief Die Klasse enthaelt die ganze Spiellogik.
*
*       Die Klasse enthaelt die Methoden und Algorithmus, die ein lauffaehiges und eindeutig loesbares klassisches 9x9-Sudoku erstellen.
*       Hier wird das eigentliche 9x9-Sudoku-Spiel generiert.
*/
class Logic
{
public:
    /** \fn Logic()
    *
    *   \brief Konstruktor
    *
    *      Der Konstruktor initialisiert die 2 Matrizen mit 0-en,
    *      wo das geloeste Sudoku und Sudoku fuer Spieler gespeichert werden muessen.
    */
    Logic( int _level);


    /** \fn ~Sudo()
    *
    *   \brief Destruktor gibt den reservierten Speicher frei.
    */
    ~Logic();


    /** \fn     getNumberReady()
    *
    *   \brief
    *
    *   \return
    */
    int getNumberReady( int , int ) const;


    /** \fn     getNumberReady()
    *
    *   \brief
    *
    *   \return
    */
    int getNumberUser( int , int ) const;


    /** \fn     getNumberReady()
    *
    *   \brief
    */
    void setNumberUser( int, int, int );

    bool isFinished();

private:
    int m_grid9x9_ready[SIZE][SIZE]; //!< geloestes Sudoku wird gespeichert
    int m_grid9x9_user[SIZE][SIZE]; //!< Sudoku fuer den Spieler wird gespeichert

    int m_solution; //!< Anzahl der moeglichen Loesungen
    int m_elem; //!< Anzahl zu pruefenden Zellen


    /** \fn create_game()
    *
    *   \brief Die private Methode erstellt das Sudoku.
    *
    *       Die Kernmethode der Klasse Sudo ruft andere Methoden auf, die eindeutig loesbares Sudoku generieren
    *       und dem Spieler bereitstellen.
    *
    *   \param level ist das Schwierigkeitsgrad vom Spiel. Es kann 1(easy), 2(medium) oder 3(hard) sein.
    *
    *   \return Die Methode hat keinen Rueckgabewert.
    */
    bool create_game( int _level );

    /** \fn  create_sudo9x9()
    *
    *   \brief die Methode erzeugt komplett geloestes Sudoku.
    *
    *       Das komplett geloeste Sudoku wird danach in der Matrix grid9x9_ready[SIZE][SIZE] gespeichert.
    *
    *   \param  row     Zeile der Matrix
    *
    *   \param  column  Spalte der Matrix
    *
    *   \param  grid    Zeiger auf die Matrix, wo das Sudoku gespeichert werden soll
    *
    *   \return Die Methode hat 1 beim Erfolg und 0 beim Misserfolg als Rueckgabewert.
    */
    bool create_sudo9x9( int _row, int _column, int* _grid );


    /** \fn     check()
    *
    *   \brief  Die Methode prueft die Spielregeln fuer das gesamte 9x9-Spielfeld.
    *
    *           Die Methode ruft die "Untermethoden" auf, die ihre Teilregeln pruefen.
    *
    *   \param  row     Zeile der Matrix
    *
    *   \param  column  Spalte der Matrix
    *
    *   \param  number  die gesetzte Zahl, die geprueft wird
    *
    *   \param  grid    Zeiger auf die Matrix, wo das Sudoku gespeichert wird
    *
    *   \return Die Methode gibt einen boolschen Wert zurueck:
    *           true, wenn's richtig ist oder false, wenn's falsch ist.
    */
    bool check( int _row, int _column,  int _number, int* _grid );


    /** \fn     checkRow()
    *
    *   \brief  Die Methode prueft die Spielregeln fuer die einzelne Zeile.
    *
    *   \param  row     Zeile der Matrix
    *
    *   \param  number  die gesetzte Zahl, die geprueft wird
    *
    *   \param  grid    Zeiger auf die Matrix, wo das Sudoku gespeichert wird
    *
    *   \return Die Methode gibt boolschen Wert zurueck:
    *           true, wenn's richtig ist oder false, wenn's falsch ist.
    */
    bool checkRow( int _row,  int _number, int* _grid );


    /** \fn     checkColumn()
    *
    *   \brief  Die Methode prueft die Spielregeln fuer die einzelne Spalte.
    *
    *   \param  column  Spalte der Matrix
    *
    *   \param  number  die gesetzte Zahl, die geprueft wird
    *
    *   \param  grid    Zeiger auf die Matrix, wo das Sudoku gespeichert wird
    *
    *   \return Die Methode gibt boolschen Wert zurueck:
    *           true, wenn's richtig ist oder false, wenn's falsch ist.
    */
    bool checkColumn( int _column,  int _number, int* _grid );


    /** \fn     checkBox()
    *
    *   \brief  Die Methode prueft die Spielregeln fuer das 3x3-Subgrid.
    *
    *   \param  row     Zeile der Matrix
    *
    *   \param  column  Spalte der Matrix
    *
    *   \param  number  die gesetzte Zahl, die geprueft wird
    *
    *   \param  grid    Zeiger auf die Matrix, wo das Sudoku gespeichert wird
    *
    *   \return Die Methode gibt boolschen Wert zurueck:
    *           true, wenn's richtig ist oder false, wenn's falsch ist.
    */
    bool checkBox( int _row, int _column,  int _number, int* _grid );


    /** \fn copyGrid9x9()
    *
    *   \brief Hilfsmethode
    *
    *       Die Methode kopiert das erzeugte Sudoku von *grid9x9_ready[SIZE][SIZE]
    *       nach *grid9x9_user[SIZE][SIZE].
    *
    *   \return Die Methode hat keinen Rueckgabewert.
    */
    void copyGrid9x9();


    /** \fn removeRandomCells()
    *
    *   \brief Hilfsmethode
    *
    *       Die Methode entfernt zufaellig eine Zahl aus dem Spielfeld und prueft dannach, ob das Sudoku
    *       immer noch eindeutig loesbar ist. Die Anzahl der zu entfernenden Zahlen wird nach dem Schwierigkeitsgrad
    *       bestimmt. Der Algorithmus ist so implementiert, dass die entfernte Zahl wieder zurueckgesetzt wird, wenn
    *       das Sudoku mehrdeutig wird.
    *
    *   \param level ist das Schwierigkeitsgrad vom Spiel. Es kann 1(easy), 2(medium) oder 3(hard) sein.
    *
    *   \return Die Methode hat keinen Rueckgabewert.
    */
    void removeRandomCells( int _level );


    /** \fn checkUnique()
    *
    *   \brief Hilfsmethode
    *
    *       Die Methode prueft, ob Sudoku immer noch eindeutig loesbar ist,
    *       d.h. nur eine Loesung hat.
    *
    *   \param  grid ist ein Zeiger von Typ Integer
    *
    *   \return Die Methode gibt boolschen Wert zurueck:
    *           true, wenn's eindeutig ist oder false, wenn's mehrdeutig ist.
     */
    bool checkUnique( int* _grid );


    /** \fn     countSolutions()
    *
    *   \brief  Die Methode zaehlt die Anzahl der moeglichen Loesungen.
    *
    *   \param  row  Zeile der Matrix
    *
    *   \param  column  Spalte der Matrix
    *
    *   \param  grid    Zeiger auf die Matrix, wo das Sudoku gespeichert wird
    *
    *   \return Die Methode gibt die Anzahl der moeglichen Loesungen vom Sudoku zurueck.
    */
    int countSolutions( int _row, int _column, int* _grid );


    /** \fn     countEmpty()
    *
    *   \brief  Die Methode zaehlt die Anzahl der freien Zellen im grid9x9_user[SIZE][SIZE].
    *
    *   \return Die Methode gibt die Anzahl der freien Zellen zurueck.
    */
    int countEmpty();
};

#endif // LOGIC_H
